import re, math

def moire_freq(u_g, u_s, theta):
    m, n = 0, 0
    while m < u_g * math.sin(theta)/u_s - 0.5:
        m += 1
    while n < u_g * math.cos(theta)/u_s - 0.5:
        n += 1
    return math.sqrt((u_g * math.sin(theta) - m * u_s)**2 + (u_g * math.cos(theta) - n * u_s)**2)

def Attenuation(f0, SID, c, r, z):
    '''
    f0: Focal distance of Grid
    SID: Real SID
    c: Center to edge distanct of Grid
    r: Grid ratio
    z: Deviation between Grid center and FPD center (- left, + right)
    '''
    left = min(r * abs((c + z) / SID - c / f0), 1)
    right = min(r * abs((c - z) / SID - c / f0), 1)
    return left, right

def SID_Range(f0, c, r, V, z):
    '''
    f0: Focal distance of Grid
    c: Center to edge distanct of Grid
    r: Grid ratio
    V: Tolerance of edge radiation lost (0~1)
    z: Deviation between Grid center and FPD center
    '''
    min = (c + abs(z)) / (c / f0 + V / r)
    try:
        max = (c - abs(z)) / (c / f0 - V / r)
    except:
        max = float('inf')
    if max < 0:
        max = float('inf')
    elif min > max:
        min = max = 0
    return min, max

def isnum(x):
    rx = r'\d+\.?\d*([eE]\-?\d*)?$'
    reg = re.fullmatch(rx, x) or x == ''
    if reg:
        return True
    else:
        return False
    
def isnum_(x):
    rx = r'[\+\-]?\d+\.?\d*([eE]\-?\d*)?$'
    reg = re.fullmatch(rx, x) or x == ''
    if reg:
        return True
    else:
        return False